#ifndef _FLASH_BOARD_H_
#define _FLASH_BOARD_H_

#include <stdio.h>
// #include <config.h>
#include <stdbool.h>


#define Version                                           "EC01_251119_YG_B_G_ST01"

// 最大写入失败次数
#define FLASH_MAX_REWRITE_NUMBER                             (5ul)
// 一扇区容量
#define FLASH_MAX_SECTOR_SIZE                                (4096ul)
// 数据读取最大长度
#define FLASH_MAX_OPERATION_LENGTH                           (448 * 1024) 

// 内存操作起始地址
#define FLASH_START_WRITE_ADDRESS                            (0ul)

/* 固件地址划分 */
// 引导程序占用扇区数量 - 24Kbytes
#define BOOTLOADER_SECTOR_SIZE                               (5ul)
// 引导程序占用空间大小
#define BOOTLOADER_ACTUAL_OCCUPIED_SPACE                     (BOOTLOADER_SECTOR_SIZE * FLASH_MAX_SECTOR_SIZE)
// 引导程序分区起始地址
#define BOOTLOADER_START_SECTOR_APDR                         FLASH_START_WRITE_ADDRESS
// 引导程序分区结束地址
#define BOOTLOADER_END_SECTOR_APDR                           (BOOTLOADER_START_SECTOR_APDR + BOOTLOADER_ACTUAL_OCCUPIED_SPACE)
// 跳转到引导程序
#define JUMP_BOOTLOADER_APPLICATION                          ((void (*)(void))((uint32_t *)BOOTLOADER_START_SECTOR_APDR))

// 应用程序占用扇区数量 - 80Kbytes
#define APPLICATION_RUN_SECTOR_SIZE                              (20ul)
// 应用程序占用空间大小
#define APPLICATION_ACTUAL_RUN_OCCUPIED_SPACE                    (APPLICATION_RUN_SECTOR_SIZE * FLASH_MAX_SECTOR_SIZE)
// 应用程序分区起始地址
#define APPLICATION_START_RUN_SECTOR_ADDR                        BOOTLOADER_END_SECTOR_APDR
// 应用程序分区结束地址
#define APPLICATION_END_RUN_SECTOR_ADDR                          (APPLICATION_START_RUN_SECTOR_ADDR + APPLICATION_ACTUAL_RUN_OCCUPIED_SPACE)
// 跳转应用程序方法
#define JUMP_FIRMWARE_RUN_APPLICATION                            ((void (*)(void))((uint32_t *)APPLICATION_START_RUN_SECTOR_ADDR))

// 应用程序备份扇区数量 - 80Kbytes
#define APPLICATION_BACKUP_SECTOR_SIZE                              (20ul)
// 应用程序占用空间大小
#define APPLICATION_ACTUAL_BACKUP_OCCUPIED_SPACE                    (APPLICATION_BACKUP_SECTOR_SIZE * FLASH_MAX_SECTOR_SIZE)
// 应用程序分区起始地址
#define APPLICATION_START_BACKUP_SECTOR_ADDR                        APPLICATION_END_RUN_SECTOR_ADDR
// 应用程序分区结束地址
#define APPLICATION_END_BACKUP_SECTOR_ADDR                          (APPLICATION_START_BACKUP_SECTOR_ADDR + APPLICATION_ACTUAL_BACKUP_OCCUPIED_SPACE)
// 跳转应用程序方法
#define JUMP_FIRMWARE_BACKUP_APPLICATION                            ((void (*)(void))((uint32_t *)APPLICATION_START_BACKUP_SECTOR_ADDR))

// 应用程序OTA扇区数量 - 80Kbytes
#define APPLICATION_OTA_SECTOR_SIZE                              (20ul)
// 应用程序占用空间大小
#define APPLICATION_ACTUAL_OTA_OCCUPIED_SPACE                    (APPLICATION_OTA_SECTOR_SIZE * FLASH_MAX_SECTOR_SIZE)
// 应用程序分区起始地址
#define APPLICATION_START_OTA_SECTOR_ADDR                        APPLICATION_END_BACKUP_SECTOR_ADDR
// 应用程序分区结束地址
#define APPLICATION_END_OTA_SECTOR_ADDR                          (APPLICATION_START_OTA_SECTOR_ADDR + APPLICATION_ACTUAL_OTA_OCCUPIED_SPACE)
// 跳转应用程序方法
#define JUMP_FIRMWARE_OTA_APPLICATION                            ((void (*)(void))((uint32_t *)APPLICATION_START_OTA_SECTOR_ADDR))

#define FIRMWARE_USE_ADDR                                         0x3000 

#define WriteEepromSize                                           1
/**
 * @brief 扇区擦除
 *
 * @param EraseStartAddr - 擦除的扇区
 * @param EraseSize      - 擦除的长度
 */
extern void FlashEraseBlock(uint32_t EraseStartAddr, uint32_t EraseSize);

/**
 * @brief 读取缓存的数据
 *
 * @param ReadStartAddr - 读取起始地址
 * @param pDataOut      - 指向保存数据地址的指针变量
 * @param SizeOut       - 读取数据长度
 */
extern void FlashReadCacheData(uint32_t ReadStartAddr, void *pDataOut, uint32_t SizeOut);

/**
 * @brief 写入一定长度的数据并验证是否成功
 *
 * @param WriteStartAddr - 写入起始地址
 * @param pDataIn        - 指向写入数据地址的指针变量
 * @param SizeIn         - 写入数据长度
 * @return bool          - 写入状态（true：成功 false：失败）
 */
extern bool FlashWriteCacheDataToCheak(uint32_t WriteStartAddr, const void *pDataIn, uint32_t SizeIn);

/**
 * @brief 计算文件的累加校验码
 * 
 * @param AddressOffset - 文件的起始地址偏移量
 * @param FilzeSize     - 文件的大小
 * @return uint8_t      - 计算得到的累加校验码，取低 8 位
 */
extern uint8_t FlashCalculateFileAccumulateCleckCode(uint32_t AddressOffset, uint32_t FilzeSize);

#endif
